package com.gitee.wsl.compose.ui.text

import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
import com.gitee.wsl.compose.ui.base.Text
import com.gitee.wsl.compose.ui.theme.toColor
import com.gitee.wsl.compose.ui.theme.currentThemeColor
import com.gitee.wsl.compose.ui.theme.currentThemeTypography
//import com.google.accompanist.placeholder.material.placeholder
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.material3.LocalTextStyle
import androidx.compose.ui.text.TextStyle
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource



@Composable
fun Text.NoteContent(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = currentThemeColor.textColorPrimary.toColor(),
    textAlign: TextAlign = TextAlign.Start
) {
    Text(
        text = text,
        modifier = modifier,
        fontSize = 17.sp,
        color = color,
        textAlign = textAlign
    )
}

@Composable
fun Text.Content(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = currentThemeColor.textColorSecondary.toColor(),
    maxLines: Int = 99,
    textAlign: TextAlign = TextAlign.Start,
    canCopy: Boolean = false,
    isLoading: Boolean = false
) {
    if (canCopy) {
        SelectionContainer {
            Title(
                title = text,
                modifier = modifier,
                fontSize = currentThemeTypography.h6.fontSize,
                color = color,
                maxLine = maxLines,
                textAlign = textAlign,
                isLoading = isLoading
            )
        }
    } else {
        Title(
            title = text,
            modifier = modifier,
            fontSize = currentThemeTypography.h5.fontSize,
            color = color,
            maxLine = maxLines,
            textAlign = textAlign,
            isLoading = isLoading
        )
    }
}

@Composable
fun Text.Mini(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = currentThemeColor.textColorSecondary.toColor(),
    maxLines: Int = 1,
    textAlign: TextAlign = TextAlign.Start,
    isLoading: Boolean = false
) {
    Title(
        title = text,
        modifier = modifier,
        fontSize = currentThemeTypography.h6.fontSize,
        color = color,
        maxLine = maxLines,
        textAlign = textAlign,
        isLoading = isLoading,
    )
}

@Composable
fun Text.BigTitle( title: String,
              modifier: Modifier = Modifier,) {
    Title(
        title = title,
        modifier = modifier,
        fontSize = currentThemeTypography.h3.fontSize,
        color =  currentThemeColor.textColorPrimary.toColor()
    )
}
@Composable
fun Text.Secondary(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = currentThemeColor.textColorSecondary.toColor(),
    maxLines: Int = 1,
    textAlign: TextAlign = TextAlign.Start,
    isLoading: Boolean = false
) {
    Text(
        text = text,
        /*modifier = modifier.placeholder(
            visible = isLoading,
        ),*/
        fontSize = 15.sp,
        color = color,
        maxLines = maxLines,
        overflow = TextOverflow.Ellipsis,
        textAlign = textAlign
    )
}

@Composable
fun Text.Annotated(
    text: AnnotatedString,
    modifier: Modifier = Modifier,
    fontSize: TextUnit = currentThemeTypography.h6.fontSize,
    textAlign: TextAlign = TextAlign.Start,
    fontWeight: FontWeight = FontWeight.Normal,
    canCopy: Boolean = false,
    isLoading: Boolean = false
) {
    if (canCopy) {
        SelectionContainer {
            Text(
                text = text,
                /*modifier = modifier
                    .placeholder(
                        visible = isLoading,
                        color = currentThemeColor.onBackground.toColor()
                    ),*/
                fontWeight = fontWeight,
                fontSize = fontSize,
                overflow = TextOverflow.Ellipsis,
                textAlign = textAlign
            )
        }
    } else {
        Text(
            text = text,
            /*modifier = modifier
                .placeholder(
                    visible = isLoading,
                    color = currentThemeColor.onBackground.toColor()
                ),*/
            fontWeight = fontWeight,
            fontSize = fontSize,
            overflow = TextOverflow.Ellipsis,
            textAlign = textAlign
        )
    }
}

@Composable
fun Text.Title(
    title: String,
    modifier: Modifier = Modifier,
    fontSize: TextUnit = 16.sp,
    color: Color = currentThemeColor.textColorPrimary.toColor(),
    fontWeight: FontWeight = FontWeight.Bold,
    maxLine: Int = 1,
    textAlign: TextAlign = TextAlign.Start,
    isLoading: Boolean = false
) {
    Text(
        text = title,
        /*modifier = modifier
            .placeholder(
                visible = isLoading,
                color = currentThemeColor.shadow.toColor()
            ),*/
        fontWeight = fontWeight,
        fontSize = fontSize,
        color = color,
        maxLines = maxLine,
        overflow = TextOverflow.Ellipsis,
        textAlign = textAlign
    )
}

/** 关键词高亮显示 */
@Composable
fun Text.Highlighted(
    content: String,
    highlighted: String,
    highlightColor: Color = currentThemeColor.textColorLink.toColor()
) {
    val splitContent = content.split(highlighted, ignoreCase = true)
    val annotatedText = buildAnnotatedString {
        for (i in splitContent.indices) {
            withStyle(style = SpanStyle(color = currentThemeColor.textColorSecondary.toColor())) {
                append(splitContent[i])
            }
            if (i != splitContent.size - 1) {
                withStyle(style = SpanStyle(color = highlightColor)) {
                    append(highlighted)
                }
            }
        }
    }

    Text(
        annotatedText, maxLines = 1,
        overflow = TextOverflow.Ellipsis,
    )
}

/**
 * Displays a headline text by passing all of the provided parameters to [Text] and also passing
 * [Typography.headlineMedium] as `style`. A headline should be used sparingly for important texts
 * or numerals. In places where `style` should derived from the [LocalTextStyle] provided by the
 * [MaterialTheme] components, make sure you use [Text] directly.
 */
@Composable
fun Text.Headline(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    onTextLayout: (TextLayoutResult) -> Unit = {},
) {
    Text(
        text, modifier, color, fontSize, fontStyle, fontWeight, fontFamily, letterSpacing,
        textDecoration, textAlign, lineHeight, overflow, softWrap, maxLines, minLines, onTextLayout,
        style = MaterialTheme.typography.headlineMedium
    )
}

/**
 * Displays a label text by passing all of the provided parameters to [Text] and also passing
 * [Typography.labelMedium] as `style`. A label should be used sparingly for small pieces of text,
 * to annotate imagery or to introduce a headline. In places where `style` should derived from the
 * [LocalTextStyle] provided by the [MaterialTheme] components, make sure you use [Text] directly.
 */
@Composable
fun Text.Label(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    onTextLayout: (TextLayoutResult) -> Unit = {},
) {
    Text(
        text, modifier, color, fontSize, fontStyle, fontWeight, fontFamily, letterSpacing,
        textDecoration, textAlign, lineHeight, overflow, softWrap, maxLines, minLines, onTextLayout,
        style = MaterialTheme.typography.labelMedium
    )
}


/*
@Preview
@Composable
fun TextPreview() {
    Column {
        Text.Headline("Head\nline")
        Text.Title("Title\ntitle")
        Text.Content("Body\nbody")
        Text.Label("Label\nbody")
    }
}*/


@Composable
fun Text(
    text: StringResource,
    modifier: Modifier = Modifier,
    style: TextStyle = LocalTextStyle.current,
    color: Color = Color.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    textAlign: TextAlign? = null,
    overflow: TextOverflow = TextOverflow.Clip,
    lines: Int? = null,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
) {
    Text(
        modifier = modifier,
        text = stringResource(resource = text),
        style = style,
        color = color,
        fontStyle = fontStyle,
        fontWeight = fontWeight,
        textAlign = textAlign,
        overflow = overflow,
        lines = lines,
        maxLines = lines ?: maxLines,
        minLines = lines ?: minLines,
    )
}

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    style: TextStyle = LocalTextStyle.current,
    color: Color = Color.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    textAlign: TextAlign? = null,
    overflow: TextOverflow = TextOverflow.Clip,
    lines: Int? = null,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
) {
    var textValue = text

    Text(
        modifier = modifier,
        text = textValue,
        color = color,
        fontStyle = fontStyle,
        fontWeight = fontWeight,
        textAlign = textAlign,
        overflow = overflow,
        maxLines = lines ?: maxLines,
        minLines = lines ?: minLines,
        style = style,
        onTextLayout = { textLayoutResult ->
            lines?.let { exactLines ->
                val linesDiff = exactLines - textLayoutResult.lineCount
                if (linesDiff > 0) {
                    textValue = text.addEmptyLines(linesDiff)
                }
            }
        }
    )
}

@Composable
fun Text(
    text: AnnotatedString,
    modifier: Modifier = Modifier,
    style: TextStyle = LocalTextStyle.current,
    color: Color = Color.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    textAlign: TextAlign? = null,
    overflow: TextOverflow = TextOverflow.Clip,
    lines: Int? = null,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    inlineContent: Map<String, InlineTextContent> = mapOf(),
) {
    Text(
        modifier = modifier,
        text = text,
        color = color,
        fontStyle = fontStyle,
        fontWeight = fontWeight,
        textAlign = textAlign,
        overflow = overflow,
        maxLines = lines ?: maxLines,
        minLines = lines ?: minLines,
        style = style,
        inlineContent = inlineContent,
    )
}

private fun String.addEmptyLines(lines: Int) = this + "\n ".repeat(lines)